package LogicSide;

import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import tables.UserHistory;

import DBside.JDBCConnection;
import DBside.JDBCConnection.Table;
import DBside.TableItem;
import DBside.Tools;
import DBside.Tools.History;

public class HistoryModifier {

	public static void main(String[] args) throws Exception {
		JDBCConnection con = new JDBCConnection();
		con.openConnection(Tools.LocalURL, Tools.LocaluserName,
				Tools.Localpassword);
		Session s = new Session();
		s.setCon(con);
		java.util.Date today = new java.util.Date();
		// addHistoryItem(s,"zion","Meet Me At The Roxy",History.ADDEDSONG,new
		// java.sql.Date(today.getTime()));
		// for(UserHistory h: getAllFollowHistory("avigdor", s))
		// System.out.println(h.getDescription());
	}

	/**
	 * 
	 * @param s
	 * @return return all UserHistory of all users which session user follow,
	 *         might be empty
	 * @throws SQLException
	 */
	public static List<UserHistory> getAllFollowHistory(Session s)
			throws SQLException {
		List<UserHistory> history = new ArrayList<UserHistory>();
		List<String> str = FollowersModifier.getAllFollowed(s);
		for (String st : str) {
			history.addAll(getUserHistory(st, s));
		}
		return history;
	}

	/**
	 * 
	 * @param user_name
	 * @param s
	 * @return UserHistory of the given user_name, might be empty
	 * @throws SQLException
	 */
	public static List<UserHistory> getUserHistory(String user_name, Session s) throws SQLException {
		List<UserHistory> history = new ArrayList<UserHistory>();
		UserHistory temp;
		int user_id, type;
		History h = null;
		int id=-1;
		ResultSet hrs = null;
		TableItem[] ti = new TableItem[1];
		try {
			s.getCon().getConnection().setAutoCommit(false);
			user_id = s.getCon().selectById(user_name, Table.USER);
			if (user_id == -1)
			{
				s.getCon().getConnection().commit();
				return history;
			}
			
			// now take all tupples of history
			ti[0] = new TableItem("userId", Tools.Type.INT, user_id);
			hrs = s.getCon().select("entityId,type,date", ti, null, null,
					JDBCConnection.Table.USERHESTORY);
			if (Tools.isEmpty(hrs)) // no history
				{
				s.getCon().getConnection().commit();
				return history;
			}
			while (hrs.next()) {
				type = hrs.getInt("type");
				for (History h1 : History.values()) {// should be fail safe
					if (h1.getTypeCode() == type)
						h = h1;
				}
				id= hrs.getInt("entityId");
				temp = new UserHistory(user_id,id, h,
						hrs.getDate("date"));
				temp.setSong_id(id);
				String desc = getDescriptionOfHistory(temp, user_name, s);
				if(desc!=null)
				if (!desc.equals("")) {
					temp.setDescription(desc);
					history.add(temp);
				}
			}
			s.getCon().getConnection().commit();
			
		} catch (SQLException e) {
			if (s.getCon().getConnection() != null)
				s.getCon().getConnection().rollback();
		} finally {
			if (hrs != null)
				hrs.close();
		}
		return history;
	}

	/** 
	 * get user history for a user and do the same last action.
	 * @param h
	 * @param s
	 * @throws SQLException
	 */
	public static void doTheSame(UserHistory h,Session s) throws SQLException
	{
		switch(h.getHistory())
		{
		case ADDEDFOLLOWER:
		{
			try {
				s.getCon().getConnection().setAutoCommit(false);
				FollowersModifier.addFollow(h.getEntity_name(), s);
				s.getCon().getConnection().commit();
			} catch (SQLException e) {
				if(s.getCon().getConnection()!=null)
					s.getCon().getConnection().rollback();
				e.printStackTrace();
			}
			break;
		}
		case ADDEDSONG:
		{
			System.out.println("the song is:"+h.getSong_id());
			ManageSongs.addSongToUser(h.getSong_id(), h.getEntity_name(), s);
			break;
		}
		case CREATEDPLAYLIST:
		{
			break;
		}
	}
		
		
		
		
	}
	/**
	 * 
	 * @param h
	 * @param user_name
	 * @param s
	 * @return String describing a single UserHistory, empty string for error
	 * @throws SQLException
	 */
	public static String getDescriptionOfHistory(UserHistory h,
			String user_name, Session s) throws SQLException {
		ResultSet ers = null;
		String des = "", entity_name = null;
		// getting date
		TableItem[] ti = new TableItem[2];
		ti[0] = new TableItem("userId", Tools.Type.INT, h.getIdA());
		ti[1] = new TableItem("entityId", Tools.Type.INT, h.getIdB());
		try {
			s.getCon().getConnection().setAutoCommit(false);
			ers = s.getCon().select("date", ti, Tools.Connector.AND, null,
					JDBCConnection.Table.USERHESTORY);
			if (Tools.isEmpty(ers))
				return null;
			ers.last();
			des += ers.getDate("date").toString() + ": ";
			ti = new TableItem[1];
			des += user_name;
			switch (h.getHistory()) {
			case ADDEDFOLLOWER: {
				des += " now follows: ";
				entity_name = s.getCon().selectByName(h.getIdB(), Table.USER);
			}
				break;
			case ADDEDSONG:
			case LISTINTOSONG: {
				des += " added the song: ";
				entity_name = s.getCon().selectByName(h.getIdB(), Table.SONG);
			}
				break;
			case CREATEDPLAYLIST: {
				des += " created the playlist: ";
				entity_name = s.getCon().selectByName(h.getIdB(),
						Table.PLAYLIST);
			}
				break;
			default:
				return null;
			}
			if (entity_name == null)
				return null;
			h.setEntity_name(entity_name);
			des += entity_name;
			s.getCon().getConnection().commit();
		} catch (SQLException e) {
			if (s.getCon().getConnection() != null)
				s.getCon().getConnection().rollback();
		} finally {
			if (ers != null)
				ers.close();
		}
		return des;
	}

	/**
	 * 
	 * @param s
	 * @param entity_name
	 * @param type
	 * @param d
	 * @return add a single UserHistory to database, using the other procedure
	 *         for that, true for success, false otherwise
	 */
	public static boolean addHistoryItem(Session s, String entity_name,
			History type, Date d,int song_id) {
		UserHistory h;
		int uid = -1, eid = -1;
		JDBCConnection.Table t = null;
		// get the ids
		uid = s.getUser_id();
		switch (type) {
		case ADDEDFOLLOWER:
			t = Table.USER;
			break;
		case ADDEDSONG:
		case LISTINTOSONG:
			t = Table.SONG;
			break;
		case CREATEDPLAYLIST:
			t = Table.PLAYLIST;
			break;
		}
		eid = s.getCon().selectById(entity_name, t);
		h = new UserHistory(uid, eid, type, d);
		if(song_id!=-1)
			h.setSong_id(song_id);
		return addHistoryItem(h, s);

	}

	/**
	 * 
	 * @param h
	 * @param s
	 * @return add UserHistory h to user in session s, true for sucess, false
	 *         otherwise
	 */
	public static boolean addHistoryItem(UserHistory h, Session s)// no checks
																	// for
																	// doubles
	{// true for success, false otherwise
		int type = 0;
		switch (h.getHistory()) {
		case ADDEDFOLLOWER:
			type = 2;
			break;
		case ADDEDSONG:
			type = 1;
			break;
		case CREATEDPLAYLIST:
			type = 3;
			break;
		case LISTINTOSONG:
			type = 4;
			break;
		}
		TableItem[] ti = new TableItem[5];
		ti[0] = new TableItem("userId", Tools.Type.INT, h.getIdA());
		ti[1] = new TableItem("entityId", Tools.Type.INT, h.getIdB());
		ti[2] = new TableItem("type", Tools.Type.INT, type);
		ti[3] = new TableItem("date", Tools.Type.DATE, h.getDate());
		ti[4] = new TableItem("songId", Tools.Type.INT, h.getSong_id());
		ResultSet rs = s.getCon().insert(JDBCConnection.Table.USERHESTORY, ti);
		return !Tools.isEmpty(rs);
	}
}